<script setup lang="ts">
import type { MenuInfo } from 'ant-design-vue/es/menu/src/interface'
import { ref, reactive, onMounted } from 'vue'
import { useI18n } from 'vue-i18n'
import { BubbleList } from 'ant-design-x-vue'
import { UserOutlined, SettingOutlined, LogoutOutlined } from '@ant-design/icons-vue'
import { PanelRightContract24Filled } from '@vicons/fluent'
import { Icon } from '@vicons/utils'
import { emitter } from '@/utils/mitt'
import { isMobileMode } from '@/utils/detection'
import { storeToRefs } from 'pinia'
import { useUserStore } from '@/stores/user'
import { useChatStore } from '@/stores/chat'
import { useModelStore } from '@/stores/model'
import ChangeDarkmode from '@/components/ChangeDarkmode.vue'
import ChatWelcome from '@/components/chat/ChatWelcome.vue'
import ChatSender from '@/components/chat/ChatSender.vue'
import SettingModal from '@/components/setting/SettingModal.vue'
import SidePanel from './side-panel.vue'
import { message } from 'ant-design-vue'

const { t } = useI18n()

defineOptions({
  name: 'Chat',
})

// 用户存储
const userStore = useUserStore()

// 聊天存储
const chatStore = useChatStore()
const { readActiveConvKey, readActiveConvTitle, readConvsBubbleItems, isSystemTyping } =
  storeToRefs(chatStore)
// 模型存储
const modelStore = useModelStore()
const { readActiveModelInfo } = storeToRefs(modelStore)

// 状态参数
const state = reactive({
  // 当前sender中文本
  currentText: '',
  // 侧边栏是否展开
  isSidebarExpand: !isMobileMode(),
})

// 错误参数
const error = reactive({
  isShow: false,
  message: '',
  needSetting: false,
})

// 组件
const sidePanelRef = ref()
const chatSenderRef = ref()
const settingModalRef = ref()

// 菜单点击
const onMenuClick = (e: MenuInfo) => {
  switch (e.key) {
    case 'setting':
      // 设置
      emitter.emit('onShowSettingModal', { tabName: 'default' })
      break
    case 'logout':
      // 退出登录
      userStore.logoutConfirm(t('account.logout.confirmContent'), false)
      break
  }
}

// 显示设置
const handleShowSetting = () => {
  if (isMobileMode()) return
  emitter.emit('onShowSettingModal', { tabName: 'default' })
}

// 显示管理模型
const handelShowModelManage = () => {
  emitter.emit('onShowSettingModal', { tabName: 'supplier' })
}

// 切换展开
const troggerSidebar = () => {
  state.isSidebarExpand = !state.isSidebarExpand
}

// 发送消息
const handleSubmitChatting = async (content: string) => {
  const isNew = !readActiveConvKey.value
  try {
    const modelId = readActiveModelInfo.value?.id ?? ''
    await chatStore.send(modelId, content)
    if (isNew) {
      // 更新标题
      await chatStore.geneConvTitle(readActiveConvKey.value, readActiveModelInfo.value)
    }
  } catch (error) {
    message.error(error.message)
  }
}

// 打断消息
const handleAbortChatting = async () => {
  await chatStore.abort()
}

// 错误检查
const settingErrorCheck = () => {
  let errorMsg = ''
  if (!modelStore.readUsableLlmModels.length) {
    errorMsg = t('chat.error.needModel')
  }
  if (!error.isShow && errorMsg) {
    error.isShow = true
    error.message = errorMsg
    error.needSetting = true
  } else if (error.isShow && error.needSetting && !errorMsg) {
    error.isShow = false
  }
}

onMounted(async () => {
  try {
    // 初始化存储
    await chatStore.initChatStore()
    await modelStore.initModelStore()
    // 处理显示错误信息
    if (!modelStore.readActiveSuppliers.length) {
      error.isShow = true
      error.message = t('chat.error.noActiveSupplier')
    } else {
      settingErrorCheck()
    }
  } catch (e) {
    error.isShow = true
    error.message = e.message
  }
  // 监听总线：开启设置
  emitter.on('onShowSettingModal', async ({ tabName }) => {
    settingModalRef.value.open(tabName)
  })
})
</script>

<template>
  <div class="chat-container">
    <SidePanel ref="sidePanelRef" v-model:expand="state.isSidebarExpand" />
    <div class="main-panel" :class="{ welcome: readConvsBubbleItems.length <= 0 }">
      <div class="banner">
        <div class="model">
          <Icon class="mobile-slider" size="24px" @click="troggerSidebar">
            <PanelRightContract24Filled />
          </Icon>
          <div class="title">{{ readActiveConvTitle }}</div>
        </div>
        <div class="action">
          <ChangeDarkmode />
          <a-dropdown class="user" placement="bottomRight" :arrow="{ pointAtCenter: true }">
            <a-avatar @click="handleShowSetting">
              <template #icon>
                <UserOutlined />
              </template>
            </a-avatar>
            <template #overlay>
              <a-menu @click="onMenuClick">
                <a-menu-item key="setting">
                  <SettingOutlined class="mr-1" />
                  {{ t('setting.title') }}
                </a-menu-item>
                <a-menu-divider />
                <a-menu-item key="logout">
                  <LogoutOutlined class="mr-1" />
                  {{ t('account.logout.name') }}
                </a-menu-item>
              </a-menu>
            </template>
          </a-dropdown>
        </div>
      </div>
      <BubbleList
        v-if="readConvsBubbleItems.length"
        class="chater page-inner-container"
        :roles="chatStore.readChatBubbleRoles"
        :items="readConvsBubbleItems"
      />
      <div v-else class="chater !pb-0 !flex-none">
        <div class="page-container">
          <ChatWelcome />
        </div>
      </div>
      <div class="footer">
        <div class="page-container">
          <template v-if="!error.isShow">
            <ChatSender
              ref="chatSenderRef"
              v-model:value="state.currentText"
              :loading="isSystemTyping"
              @submit-chatting="handleSubmitChatting"
              @abort-chatting="handleAbortChatting"
            />
          </template>
          <template v-else>
            <n-alert :title="t('chat.error.chatUnavailable')" type="warning">
              {{ error.message }}
              <div class="mt-4" v-if="error.needSetting">
                <n-button type="primary" strong secondary @click="handelShowModelManage">
                  {{ t('model.manageModel') }}
                </n-button>
              </div>
            </n-alert>
          </template>
        </div>
      </div>
    </div>
    <SettingModal ref="settingModalRef" @close="settingErrorCheck" />
  </div>
</template>

<style lang="scss" scoped>
.chat-container {
  display: flex;
}
.mobile-slider {
  display: none;
  color: var(--vas-text-color);
}

.main-panel {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  .banner {
    display: flex;
    justify-content: space-between;
    padding: 15px;
    .model {
      flex: 1;
      width: 1px;
      display: flex;
      align-items: center;
      // flex-wrap: wrap;
      gap: 15px;
      .title {
        font-size: 18px;
        color: var(--vas-title-color);
        width: 100%;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
    }
    .action {
      display: flex;
      align-items: center;
      flex-wrap: wrap;
      gap: 15px;
      margin-left: 20px;
      .user {
        cursor: pointer;
      }
    }
  }
  :deep(.chater) {
    flex: 1;
    padding: 0 16px 40px;
  }
  .footer {
    width: 100%;
    background-color: var(--vas-main-bg);
    padding: 15px;
  }
  &.welcome {
    justify-content: center;
    .banner {
      position: absolute;
      top: 0;
      width: 100%;
    }
  }
}
@media (max-width: 767px) {
  .mobile-slider {
    display: flex;
  }
}
</style>
